package cn.remex.db;

import cn.remex.db.rsql.RsqlConstants;
import cn.remex.db.rsql.model.Modelable;
import cn.remex.db.rsql.transactional.RsqlTransaction;

import javax.persistence.ManyToMany;
import java.io.Serializable;
import java.util.Map;

public interface Container extends Serializable {
	/**
	 * 以callSql为SQL语句创建存储过程/函数等。
	 *
	 * @param callSql callSql
	 * @param <T>     t
	 * @return RsqlRvo
	 */
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> createCall(String callSql);

	<T extends Modelable, ParentType extends Modelable> T createDBBean(Class<T> clazz);

	<T extends Modelable, ParentType extends Modelable> DbCvo<T, ParentType> createDbCvo(Class<T> beanClass);

	<T extends Modelable, ParentType extends Modelable> DbCvo<T, ParentType> createDbCvo(String sqlString, Map<String, Object> params);

	<T extends Modelable, ParentType extends Modelable> DbRvo<T> delete(DbCvo<T, ParentType> dbCvo);

	/**
	 * 从数据中删除对象o。<br>
	 * 1.根据o的Class去检索BeanClass
	 * 2.根据o.getId()为主键，从数据中删除数据。
	 * 3.根据其List属性中，OneToMany/ManyToMany指定的{@link ManyToMany#cascade()}来级联删除数据.
	 *
	 * @param o   删除的对象
	 * @param <T> t
	 * @return DbRvo
	 */
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> delete(T o);

	/**
	 * 根据传入的对象类型clazz和主键id删除数据
	 *
	 * @param clazz    clazz
	 * @param idObject idObject
	 * @param <T>      t
	 * @return DbRvo
	 */
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> deleteById(Class<T> clazz, String idObject);

	/*
	 * 根据传入的sql和参数对数据进行操作<br>
	 * 如果string以"SQL_"开头则从spring的配置文件Rsql_SQL中获取真实的SQL。
	 * sql 为传入要执行的sql语句，存在where语句等条件时，条件值为 :+字段名称（命名参数），
	 * params为map 命名参数的字段名称,参数值
	 */
	@RsqlTransaction
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> execute(String sql, Map<String, Object> params);

	/**
	 * 根据传入的sql语句和参数执行数据库查询操作<br>
	 * 如果string以"SQL_"开头则从spring的配置文件Rsql_SQL中获取真实的SQL。
	 *
	 * @param sql    执行的sql语句，其中的where条件为命名参数形式，:
	 * @param params 主要为where条件中的命名参数和参数值的map
	 * @param <T>    t
	 * @return RsqlRvo
	 */
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> executeQuery(String sql, Map<String, Object> params);

	<T extends Modelable, ParentType extends Modelable> DbRvo<T> executeQuery(DbCvo<T, ParentType> dbCvo);

	/**
	 * 根据传入的sql语句和参数执行数据库更新操作<br>
	 * 如果string以"SQL_"开头则从spring的配置文件Rsql_SQL中获取真实的SQL。
	 *
	 * @param sql    执行的sql语句，其中的where条件为命名参数形式，:
	 * @param params 主要为where条件中的命名参数和参数值的map
	 * @param <T>    t
	 * @return RsqlRvo
	 */
	@RsqlTransaction
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> executeUpdate(String sql, Map<String, Object> params);

	/**
	 * 判断dataStatus及通过来检查是否在本数据库中存在该对象。<br>
	 * 本数据库中存在该对象。
	 * 需要检索的对象
	 * 如果id存在，强制是否去数据库中判断该对象是否持久化
	 *
	 * @param forceCheckFromDB forceCheckFromDB
	 * @param obj              obj
	 * @param <T>              t
	 * @return boolean 对象在数据中仅唯一存在则返回true<br>
	 * 以下情况将返回false<br>
	 * <p>obj == null <p>obj 没有getId() 和 setId() <p>obj 的属性id为空 <p>
	 * obj 的属性id有值，但在数据库中不存在<p>dataStatus为{@link RsqlConstants#DS_beanNew}
	 * <p>如果数据库查询有错误<br> <p>或者本对象所对应的类在数据中持久化的表中的数据有重复项将会跑出异常<br>
	 * 如果数据中同样id的数据存在多条则数据完整性及结构存在问题<br>
	 * 一旦出现问题说明有人在程序外修改了数据结构。
	 */
	<T extends Modelable, ParentType extends Modelable> boolean exists(T obj, boolean forceCheckFromDB);

	String getSpaceName();

	//===lambda控制方式下数据库控制接口===============//
	//用于创建lambda控制的根对象DbCvo
	void setSpaceName(String poolName);

	boolean isLocalAutoFetchObjectFiled();

	boolean isLocalAutoStoreObjectFiled();

	<T extends Modelable, ParentType extends Modelable> Class<T> obtainModelClass(String beanName);

	//===核心数据库控制接口===============//
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> query(DbCvo<T, ParentType> dbCvo);


	//===核心数据库控制内部接口===============//

	void setLocalAutoFecthObjectFiled(boolean b);

	void setLocalAutoStoreObjectFlied(boolean b);

	/**
	 * 根据传入的T&lt;T extends Modelable&gt;对象进行存储或更新
	 * 根据传入的T&lt;T extends Modelable&gt;对象进行存储或更新
	 *
	 * @param <T> t
	 * @param o   o
	 * @return DbRvo
	 */
	@RsqlTransaction
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> store(T o);

	@RsqlTransaction
	<T extends Modelable, ParentType extends Modelable> DbRvo<T> store(final T obj, final DbCvo<T, ParentType> cvo);

	<T extends Modelable, ParentType extends Modelable> DbRvo<T> update(DbCvo<T, ParentType> dbCvo);
}
